/***************************************************************************
 * Ejemplo: Metodo de Newton para obtener x tal que f(x) = 0.
 * Para una mejor compresion, ver descripcion del metodo
 ***************************************************************************/

#include <math.h>   /* Biblioteca de funciones matematicas */

/***************************************************************************
 * Definicion de la funcion matematica a la que se desea encontrar cero
 ***************************************************************************/

#define FUNCTION(x) log(x) + 3 * x - 10.8074

/***************************************************************************
 * Funcion que evalua la funcion matematica dada para un valor de x
 * recibido como argumento de entrada de tipo double. El valor de retorno
 * tambien es double. No se controla la validez de los argumentos.
 ***************************************************************************/

double f(double x) {
   return(FUNCTION(x));
}

/***************************************************************************
 * Programa que calcula x tal que f(x) = 0, empleando el metodo de Newton.
 * El proceso continua mientras el valor calculado mantenga una diferencia
 * con el valor obtenido en la iteracion anterior que sea mayor que una
 * precision dada por el usuario.
 ***************************************************************************/

main() {
   int i;              /* Contador de iteraciones */
   double xi;          /* Valor de Xi */
   double xi1;         /* Valor de Xi+1 */
   double di;          /* Para calcular el ði una sola vez */
   double precision;   /* Precision que se empleara, dada por el usuario */

   /* Se solicita al usuario el valor de X1 */
   printf("Ingrese el valor de X1: ");
   scanf("%lf", &xi1);   /* scanf requiere puntero: & */

   /* Se solicita al usuario la precision para el calculo */
   printf("Ingrese la precision para el calculo de x: ");
   scanf("%lf", &precision);   /* scanf requiere puntero: & */

   /* Ciclo que lleva a cabo el calculo: i variara de 0 en adelante */
   i = 0;
   do {
      /* Guardar el valor anterior de x */
      xi = xi1;

      /* Calcular el ði una sola vez para que el calculo sea mas rapido */
      di = 0.0001 * xi;

      /* Calcular el Xi+1 */
      xi1 = xi - di * ( f(xi) / (f(xi+di)-f(xi)) );

      /* Incrementa el contador de iteraciones */
      i = i + 1;

   /* El ciclo continua mientras la diferencia entre Xi+1 - Xi */
   /* sea mayor o igual a la precision dada por el usuario     */
   } while (fabs(xi1 - xi) >= precision);

   /* Imprime el resultado final con precision de 48 digitos decimales */
   printf("\nCalculo de x con precision %e:\n\n", precision);
   printf("x = %52.48f\n", xi1);
   printf("f(x) = %20.18f\n", f(xi1));
   /* Imprime la cantidad de iteraciones que se emplearon */
   printf("Se emplearon %d iteraciones.\n", i);
}

